package apis

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"path/filepath"
	"strconv"
	"wander-mdns/service"

	"github.com/gin-gonic/gin"
)

// 在api返回时，必须携带该值，格式为{code: 常量}，根据业务类型判断。
// 目前就三种情况，正常，参数错误，服务器内部错误。
// 在小程序端，可以通过code进行过滤，因为小程序的网络API只判断网络异常，不判断业务返回的http状态。
// 当状态不为http OK时，返回格式为{code: 错误状态码,msg: 错误信息}
// 当状态为http OK时，返回格式为{code: OK,参数可选，为业务需求返回值}
const (
	OK          int = 100
	ErrParam    int = 101 // 参数错误
	ErrInternal int = 102 // 服务器内部错误
)

// GetProductByIDParm 参数ID
type GetProductByIDParm struct {
	ID string `uri:"id" binding:"required,uuid"`
}

// GetProductByBarcodeParm 参数Barcode
type GetProductByBarcodeParm struct {
	BarCode string `uri:"barcode" binding:"required"`
}

// CreateProductParm 参数Product
type CreateProductParm struct {
	Name    string `json:"name"`
	BarCode string `json:"barcode"`
	Price   string `json:"price"`
	Desc    string `json:"desc"`
}

// UploadProductImageParam 产品图片上传参数，使用form表单进行提交
type UploadProductImageParam struct {
	ProductID string `form:"product_id"`
}

// SetupRouter 设置路由
func SetupRouter() *gin.Engine {
	// 设置在这个例程中
	productStore := service.NewInMemoryProductStore()
	imageStore := service.NewDiskImageStore("uploads/images")
	productService := service.NewProductService(productStore, imageStore)
	createProductRequest := service.CreateProductRequest{
		Product: &service.Product{
			ID:      "93208967-5cb9-4f34-a0c4-c58e6dcb9386",
			Name:    "演示产品",
			BarCode: "9787302461395",
			Price:   100.0,
			Desc:    "演示产品，起演示作用",
		},
	}
	// 初始化一条数据做演示使用
	productService.CreateProduct(context.Background(), &createProductRequest)

	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
	// 最大上传大小8MB
	r.MaxMultipartMemory = 8 << 20
	r.Static("/static", "./static")
	r.StaticFile("/favicon.ico", "./favicon.ico")
	r.LoadHTMLGlob("templates/*")
	// 小程序ping
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"msg": "pong",
		})
	})
	// web页面首页
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", gin.H{
			"label":      "局域网通讯小助手",
			"title":      "局域网通讯小助手",
			"title_desc": "配合《爱上随机数》小程序使用",
			"content":    "局域网通讯小助手，提供mDns服务，HTTP服务，有产品查询、添加产品、上传产品图片、下载产品文件等演示功能，更多功能开发中！如果您觉得该应用对您有帮助，请在《爱上随机数》小程序中点击您喜欢的广告支持我，谢谢！",
		})
	})

	// 下载产品图片
	r.GET("/getProductFile/:id", func(c *gin.Context) {
		var parm GetProductByIDParm
		if err := c.ShouldBindUri(&parm); err != nil {
			c.JSON(400, gin.H{"code": ErrParam, "msg": err.Error()})
			return
		}
		if parm.ID == "93208967-5cb9-4f34-a0c4-c58e6dcb9386" {
			//c.Request.Response.Header.Set("Content-Type", "application/pdf")
			c.File("downloads/product_demo.pdf")
		} else {
			c.JSON(500, gin.H{"code": ErrParam, "msg": "暂不支持其它产品ID"})
		}

	})

	// 上传产品图片
	r.POST("/uploadProductImage", func(c *gin.Context) {
		var param UploadProductImageParam
		file, err := c.FormFile("file")
		if err != nil {
			fmt.Println(err)
			return
		}
		log.Println(file.Filename)
		imageType := filepath.Ext(file.Filename)
		err = c.ShouldBind(&param)
		if err != nil {
			c.JSON(400, gin.H{"code": ErrParam, "msg": err.Error()})
			return
		}

		req := service.UploadProductImageRequest{
			ProductID: param.ProductID,
			ImageType: imageType,
			SrcFile:   file,
		}
		resp, err := productService.UploadImage(c, &req)
		if err != nil {
			c.JSON(500, gin.H{"code": ErrInternal, "msg": err.Error()})
			return
		}
		imageID := resp.ImageID
		c.JSON(200, gin.H{"code": OK, "image_id": imageID})
	})

	// 通过产品ID调用产品信息，返回产品信息
	r.GET("/getProductByID/:id", func(c *gin.Context) {
		var parm GetProductByIDParm
		if err := c.ShouldBindUri(&parm); err != nil {
			c.JSON(400, gin.H{"code": ErrParam, "msg": err.Error()})
			return
		}
		req := service.FindProductRequest{
			ID: parm.ID,
		}
		resp, err := productService.FindProduct(c, &req)
		if err != nil {
			c.JSON(500, gin.H{"code": ErrInternal, "msg": err.Error()})
			return
		}
		product := resp.Product
		c.JSON(200, gin.H{"code": OK, "product": product})
	})
	// 通过产品国标码调用产品信息，返回产品信息
	r.GET("/getProductByBarcode/:barcode", func(c *gin.Context) {
		var parm GetProductByBarcodeParm
		if err := c.ShouldBindUri(&parm); err != nil {
			c.JSON(400, gin.H{"code": ErrParam, "msg": err.Error()})
			return
		}
		req := service.FindProductRequest{
			BarCode: parm.BarCode,
		}
		resp, err := productService.FindProduct(c, &req)
		if err != nil {
			c.JSON(500, gin.H{"code": ErrInternal, "msg": err.Error()})
			return
		}
		product := resp.Product
		c.JSON(200, gin.H{"code": OK, "product": product})
	})
	// 添加产品信息，返回ID
	r.POST("/addProduct", func(c *gin.Context) {
		var parm CreateProductParm
		err := c.ShouldBindJSON(&parm)
		if err != nil {
			c.JSON(400, gin.H{"code": ErrParam, "msg": err.Error()})
			return
		}
		price, err := strconv.ParseFloat(parm.Price, 32)
		if err != nil {
			c.JSON(500, gin.H{"code": ErrInternal, "msg": err.Error()})
			return
		}
		product := service.Product{
			Name:    parm.Name,
			BarCode: parm.BarCode,
			Price:   float32(price),
			Desc:    parm.Desc,
		}
		req := service.CreateProductRequest{
			Product: &product,
		}
		resp, err := productService.CreateProduct(c, &req)
		if err != nil {
			c.JSON(500, gin.H{"code": ErrInternal, "msg": err.Error()})
			return
		}
		id := resp.ID
		c.JSON(200, gin.H{"code": OK, "id": id})
	})
	return r
}
